﻿#include "propertyview.h"

#include <QRegularExpression>
#include <QHBoxLayout>
#include <QColor>

namespace EasyLib 
{
	PropertyView::PropertyView(QWidget* parent /*= nullptr*/)
		:QWidget(parent)
	{
		m_pIntMngCanEdit = new QtIntPropertyManager(this);
		m_pIntFac = new QtSpinBoxFactory(this);

		m_pFloatMngCanEdit = new QtDoublePropertyManager(this);
		m_pFloatFac = new QtDoubleSpinBoxFactory(this);

		m_pBoolMngCanEdit = new QtBoolPropertyManager(this);
		m_pBoolFac = new QtCheckBoxFactory(this);

		m_pStrMng = new QtStringPropertyManager(this);
		m_pStrMngCanEdit = new QtStringPropertyManager(this);

		m_pEnumMngCanEdit = new QtEnumPropertyManager(this);
		m_pEnumFac = new QtEnumEditorFactory(this);

		m_pColorMngCanEdit = new QtColorPropertyManager(this);
		m_pColorFac = new QtColorEditorFactory(this);

		m_pVec3MngCanEdit = new Vec3Manager(this);

		m_pGroupMng = new QtGroupPropertyManager(this);
		m_pStrFac = new QtLineEditFactory(this);


		auto mainLayout = new QHBoxLayout(this);
		mainLayout->setContentsMargins(0, 0, 0, 0);
		m_pBrowser = new QtTreePropertyBrowser;
		m_pBrowser->setHeaderVisible(false);
		m_pBrowser->setFactoryForManager(m_pIntMngCanEdit, m_pIntFac);
		m_pBrowser->setFactoryForManager(m_pFloatMngCanEdit, m_pFloatFac);
		m_pBrowser->setFactoryForManager(m_pBoolMngCanEdit, m_pBoolFac);
		m_pBrowser->setFactoryForManager(m_pStrMngCanEdit, m_pStrFac);
		m_pBrowser->setFactoryForManager(m_pEnumMngCanEdit, m_pEnumFac);
		m_pBrowser->setFactoryForManager(m_pColorMngCanEdit, m_pColorFac);
		m_pBrowser->setFactoryForManager(m_pColorMngCanEdit->subIntPropertyManager(), m_pIntFac);
		m_pBrowser->setFactoryForManager(m_pVec3MngCanEdit->subDoublePropertyManager(), m_pFloatFac);

		connect(m_pIntMngCanEdit, &QtIntPropertyManager::valueChanged, this, &PropertyView::intMngValueChanged);
		connect(m_pFloatMngCanEdit, &QtDoublePropertyManager::valueChanged, this, &PropertyView::floatMngValueChanged);
		connect(m_pBoolMngCanEdit, &QtBoolPropertyManager::valueChanged, this, &PropertyView::boolMngValueChanged);
		connect(m_pStrMngCanEdit, &QtStringPropertyManager::valueChanged, this, &PropertyView::strMngValueChanged);
		connect(m_pEnumMngCanEdit, &QtEnumPropertyManager::valueChanged, this, &PropertyView::enumMngValueChanged);
		connect(m_pColorMngCanEdit, &QtColorPropertyManager::valueChanged, this, &PropertyView::colorMngValueChanged);
		connect(m_pVec3MngCanEdit, &Vec3Manager::valueChanged, this, &PropertyView::vec3MngValueChanged);

		mainLayout->addWidget(m_pBrowser);
	}

	PropertyView::~PropertyView()
	{

	}

	void PropertyView::clear()
	{
		m_pStrMng->clear();
		m_pGroupMng->clear();
	
		m_pIntMngCanEdit->clear();
		m_pFloatMngCanEdit->clear();
		m_pBoolMngCanEdit->clear();
		m_pStrMngCanEdit->clear();
		m_pEnumMngCanEdit->clear();
		m_pColorMngCanEdit->clear();
		m_pVec3MngCanEdit->clear();

		m_pBrowser->clear();
	}

	void PropertyView::setup(QVector<PropGroup> vGroup)
	{
		clear();
		m_vGroup = vGroup;

		for (auto& grp : vGroup)
		{
			auto group = m_pGroupMng->addProperty(grp.name);
			if (grp.label.size() == grp.data.size() && grp.label.size() == grp.type.size())
			{
				for (int i = 0; i < grp.label.size(); ++i)
				{
					auto prop = newProperty(grp, i);
					if (prop)
					{
						prop->setToolTip(grp.uuid);
						group->addSubProperty(prop);
					}
				}
			}

			m_pBrowser->addProperty(group);
		}
	}

	QtProperty* PropertyView::newProperty(PropGroup group, int idx)
	{
		QtProperty* prop = nullptr;
		if (group.type[idx] == "int")
		{
			prop = m_pIntMngCanEdit->addProperty(group.label[idx]);
			m_pIntMngCanEdit->setValue(prop, group.data[idx].toInt());
			if (group.min.size() == group.max.size() &&
				group.min.size() == group.step.size())
			{
				bool ok;
				group.min[idx].toInt(&ok);
				if (ok)
					m_pIntMngCanEdit->setMinimum(prop, group.min[idx].toInt());

				group.max[idx].toInt(&ok);
				if (ok)
					m_pIntMngCanEdit->setMaximum(prop, group.max[idx].toInt());

				group.step[idx].toInt(&ok);
				if (ok)
					m_pIntMngCanEdit->setSingleStep(prop, group.step[idx].toInt());
			}
		}
		else if (group.type[idx] == "float")
		{
			prop = m_pFloatMngCanEdit->addProperty(group.label[idx]);
			m_pFloatMngCanEdit->setValue(prop, group.data[idx].toFloat());
			if (group.min.size() == group.max.size() &&
				group.min.size() == group.step.size())
			{
				bool ok;
				group.min[idx].toFloat(&ok);
				if (ok)
					m_pFloatMngCanEdit->setMinimum(prop, group.min[idx].toFloat());

				group.max[idx].toFloat(&ok);
				if (ok)
					m_pFloatMngCanEdit->setMaximum(prop, group.max[idx].toFloat());

				group.step[idx].toFloat(&ok);
				if (ok)
					m_pFloatMngCanEdit->setSingleStep(prop, group.step[idx].toFloat());
			}
		}
		else if (group.type[idx] == "bool")
		{
			prop = m_pBoolMngCanEdit->addProperty(group.label[idx]);
			m_pBoolMngCanEdit->setValue(prop, group.data[idx] == "true");
		}
		else if (group.type[idx] == "string")
		{
			prop = m_pStrMngCanEdit->addProperty(group.label[idx]);
			m_pStrMngCanEdit->setRegExp(prop,QRegularExpression(".*"));
			m_pStrMngCanEdit->setValue(prop, group.data[idx]);
		}
		else if (group.type[idx] == "enum")
		{
			auto data = group.data[idx].split(";");
			if (data.size()<2)
			{
				return nullptr;
			}
			prop = m_pEnumMngCanEdit->addProperty(group.label[idx]);
			int idx = data.last().toInt();
			data.removeLast();
			m_pEnumMngCanEdit->setEnumNames(prop, data);
			if (idx < 0 || idx > data.size() - 1) idx = 0;
			m_pEnumMngCanEdit->setValue(prop,idx);
		}
		else if (group.type[idx] == "color")
		{
			auto data = group.data[idx].split(";");
			if (data.size() != 3)
			{
				return nullptr;
			}
			prop = m_pColorMngCanEdit->addProperty(group.label[idx]);
			m_pColorMngCanEdit->setValue(prop,QColor(data[0].toFloat()*255, data[1].toFloat() * 255, data[2].toFloat() * 255));
		}
		else if (group.type[idx] == "vec3")
		{
			auto data = group.data[idx].split(";");
			if (data.size() != 3)
			{
				return nullptr;
			}
			prop = m_pVec3MngCanEdit->addProperty(group.label[idx]);
			m_pVec3MngCanEdit->setValue(prop, Vec3(data[0].toFloat(), data[1].toFloat(), data[2].toFloat()));

			if (group.min.size() == group.max.size() &&
				group.min.size() == group.step.size())
			{
				bool ok;
				auto v1 = group.min[idx].toFloat(&ok);
				if(ok)
					m_pVec3MngCanEdit->setMinimum(prop, Vec3(v1, v1, v1));

				auto v2 = group.max[idx].toFloat(&ok);
				if (ok)
					m_pVec3MngCanEdit->setMaximum(prop, Vec3(v2, v2, v2));

				auto v3 = group.step[idx].toFloat(&ok);
				if(ok)
					m_pVec3MngCanEdit->setSingleStep(prop, Vec3(v3, v3, v3));
			}
		}

		return prop;
	}

	void PropertyView::intMngValueChanged(QtProperty* prop, const int value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if (m_vGroup[i].uuid != prop->toolTip())
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					m_vGroup[i].data[j] = QString::number(value);
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}

	void PropertyView::floatMngValueChanged(QtProperty* prop, const float value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if (m_vGroup[i].uuid != prop->toolTip())
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					m_vGroup[i].data[j] = QString::number(value);
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}

	void PropertyView::boolMngValueChanged(QtProperty* prop, const bool value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if (m_vGroup[i].uuid != prop->toolTip())
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					m_vGroup[i].data[j] = value ? "true" : "false";
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}

	void PropertyView::strMngValueChanged(QtProperty* prop, const QString& value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if (m_vGroup[i].uuid != prop->toolTip())
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					m_vGroup[i].data[j] = value;
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}

	void PropertyView::enumMngValueChanged(QtProperty* prop, const int value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if (m_vGroup[i].uuid != prop->toolTip())
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					auto data = m_vGroup[i].data[j];
					int idx = data.lastIndexOf(";");
					m_vGroup[i].data[j] = data.mid(0, idx) + ";" + QString::number(value);
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}

	void PropertyView::colorMngValueChanged(QtProperty* prop, const QColor& value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if (m_vGroup[i].uuid != prop->toolTip())
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					m_vGroup[i].data[j] = QString("%1;%2;%3").arg(
						QString::number(value.redF()),
						QString::number(value.greenF()),
						QString::number(value.blueF()));
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}

	void PropertyView::vec3MngValueChanged(QtProperty* prop, const Vec3& value)
	{
		for (int i = 0; i < m_vGroup.size(); i++)
		{
			//利用tooltip区分prop所在的group
			if(m_vGroup[i].uuid != prop->toolTip()) 
				continue;

			for (int j = 0; j < m_vGroup[i].label.size(); ++j)
			{
				if (m_vGroup[i].label[j] == prop->propertyName())
				{
					m_vGroup[i].data[j] = QString("%1;%2;%3").arg(
						QString::number(value.m_nX),
						QString::number(value.m_nY),
						QString::number(value.m_nZ));
				}
			}
		}
		emit signal_propertyInfo(m_vGroup);
	}


}
